package hypernexusnats

import (
	"encoding/json"
	"fmt"
	"time"
)

// Publisher 提供NATS消息发布功能
type Publisher struct {
	client *NatsClient
}

// Message 表示要发布的消息
type Message struct {
	ID        string      `json:"id"`        // 消息唯一标识符
	Timestamp int64       `json:"timestamp"` // 消息时间戳
	Topic     string      `json:"topic"`     // 消息主题
	Source    string      `json:"source"`    // 消息来源
	Data      interface{} `json:"data"`      // 消息数据
}

// NewPublisher 创建一个新的Publisher实例
func NewPublisher(client *NatsClient) *Publisher {
	return &Publisher{
		client: client,
	}
}

// PublishJSON 将对象编码为JSON并发布
func (p *Publisher) PublishJSON(subject string, data interface{}) error {
	if p.client == nil {
		return fmt.Errorf("NATS客户端未初始化")
	}

	// 编码为JSON
	jsonData, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("JSON编码失败: %v", err)
	}

	// 发布消息
	return p.client.Publish(subject, jsonData)
}

// PublishMessage 发布标准格式的消息
func (p *Publisher) PublishMessage(topic string, source string, data interface{}) error {
	if p.client == nil {
		return fmt.Errorf("NATS客户端未初始化")
	}

	// 创建消息
	msg := Message{
		ID:        generateUniqueID(),
		Timestamp: time.Now().UnixNano(),
		Topic:     topic,
		Source:    source,
		Data:      data,
	}

	// 编码为JSON
	jsonData, err := json.Marshal(msg)
	if err != nil {
		return fmt.Errorf("JSON编码失败: %v", err)
	}

	// 发布消息
	return p.client.Publish(topic, jsonData)
}

// RequestJSON 发送请求并等待JSON响应
func (p *Publisher) RequestJSON(subject string, data interface{}, response interface{}, timeout time.Duration) error {
	if p.client == nil {
		return fmt.Errorf("NATS客户端未初始化")
	}

	// 编码为JSON
	jsonData, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("JSON编码失败: %v", err)
	}

	// 发送请求
	msg, err := p.client.Request(subject, jsonData, timeout)
	if err != nil {
		return err
	}

	// 解码响应
	if response != nil {
		err = json.Unmarshal(msg.Data, response)
		if err != nil {
			return fmt.Errorf("JSON解码失败: %v", err)
		}
	}

	return nil
}

// 生成唯一ID
func generateUniqueID() string {
	return fmt.Sprintf("%d-%d", time.Now().UnixNano(), time.Now().UnixNano()%1000)
}
